package syntax;

//Lembrar que o compilador implementado é baseado no java 1.4, inclusive o aspectJ
//Assim, esse código não contém generics, por exemplo List<Formal> 

import polyglot.ast.*;
import polyglot.ext.jl.ast.Term_c;
import polyglot.types.Flags;
import polyglot.types.TypeSystem;
import polyglot.util.Position;
import polyglot.util.TypedList;
import polyglot.visit.CFGBuilder;
import xaj.xc.ast.ListNode;
import xaj.xc.ast.NodeXAJ;
import xaj.xc.ast.XAJNodeFactory;
import abc.aspectj.ast.*;
import abc.aspectj.types.AJTypeSystem;
import abc.aspectj.visit.AspectMethods;

import java.util.LinkedList;
import java.util.List;

public class MultiIntro extends Term_c implements IntertypeDecl, NodeXAJ {

	/*@grammar extends intertype_member_declaration {
		MultiIntro ->
			m = modifiers_opt
			t = type
			id1 = IDENTIFIER
			"+." id2 = IDENTIFIER
			"(" p = formal_parameter_list_opt ")"
			b = block
		{:
			String c = id1.getIdentifier(); 
            String n = id2.getIdentifier();
            MultiIntro x = new MultiIntro(parser.pos(m, b), m, t, c, n, p, b);		
			RESULT = x; 
		:}
        |
			m = modifiers_opt
			"void"
			id1 = IDENTIFIER
			"+." id2 = IDENTIFIER
			"(" p = formal_parameter_list_opt ")"
			b = block
        {:
            TypeNode voidn =  parser.nf.CanonicalTypeNode(parser.pos(t),
                                                  parser.ts.Void());
            String c = id1.getIdentifier(); 
            String n = id2.getIdentifier();
            MultiIntro x = new MultiIntro(parser.pos(m, b), m, voidn, c, n, p, b);
            RESULT = x;
        :}
		;
	}*/
	
	private Flags modifiers;
	private TypeNode type;
	private String cl, name;
	private List/*<Formal>*/ param;
	private Block block;

	public MultiIntro(Position pos, Flags m, TypeNode t, String c, String n, List l, Block b) {
		super(pos);
		modifiers = m;
		type = t;
		cl = c;
		name = n;
		param = l;
		block = b;
	}

	@Override
	public List acceptCFG(CFGBuilder v, List succs) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Term entry() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public TypeNode host() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Expr thisReference(AJNodeFactory nf, AJTypeSystem ts) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void aspectMethodsEnter(AspectMethods visitor) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Node aspectMethodsLeave(AspectMethods visitor, AJNodeFactory nf,
			AJTypeSystem ts) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Node desugar(NodeFactory ft, TypeSystem ts) {
		//TableResolver ts = ct.typeSystem().parsedResolver();
		XAJNodeFactory nf = (XAJNodeFactory) ft;		
		//AJTypeSystem ts = (AJTypeSystem) ct.typeSystem();
		
		//Procura todas as classe que são subtipos de cl (Expr no exemplo visitorxaj)
		//Para este exemplo e estou fazendo manualmente, porém
		//é necessário criar uma biblioteca para realizar essa operação
		// na AST.
		TypeNode sum, mult, number;		
		sum = nf.AmbTypeNode(position(), "Sum");
		mult = nf.AmbTypeNode(position(), "Mult");
		number = nf.AmbTypeNode(position(), "Number");
		
		//Para cada subclasse um introduced é construido
		IntertypeMethodDecl suminter, multinter, numberinter;
		
		List sumth = new TypedList(new LinkedList(), TypeNode.class, false);
		suminter = nf.IntertypeMethodDecl(position(), modifiers, type, sum,
				name, param, sumth, block);
		
		List multth = new TypedList(new LinkedList(), TypeNode.class, false);
		multinter = nf.IntertypeMethodDecl(position(), modifiers, type, mult,
				name, param, multth, block);
		
		List numberth = new TypedList(new LinkedList(), TypeNode.class, false);
		numberinter = nf.IntertypeMethodDecl(position(), modifiers, type, number,
				name, param, numberth, block);
		
		List list = new TypedList(new LinkedList(), ClassMember.class, false);
		list.add(suminter);
		list.add(multinter);
		list.add(numberinter);
		
		//Criar um novo Nó do tipo Lista
		ListNode listnode = nf.ListNode(position(), list);
		
		return listnode;
		//return suminter;
	}
	

}
